package com.grm.common.utils;

import com.grm.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.beans.BeanUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * list封装为树的工具类
 *
 * @author gaorimao
 */
@Slf4j
public class TreeUtils {

    private static final String KEY_NAME = "id";
    private static final String PARENT_FIELD_NAME = "parentId";
    private static final String CHILDREN_FIELD_NAME = "children";

    /**
     * 把列表转换为树结构
     *
     * @param originalList 原始list数据
     * @return 组装后的集合
     */
    public static <T> List<T> getTree(List<T> originalList) {
        List<T> topList = new ArrayList<>();
        try {
            for (T t : originalList) {
                Long parentId = (Long) BeanUtils.getPropertyDescriptor(t.getClass(), PARENT_FIELD_NAME)
                        .getReadMethod().invoke(t);
                if (parentId == 0L) {
                    topList.add(t);
                }
            }
            originalList.removeAll(topList);
            fillTree(topList, originalList, PARENT_FIELD_NAME, CHILDREN_FIELD_NAME);
        } catch (Exception e) {
            log.error("转化树结构出现异常：", e);
            throw new BusinessException(500, "转化树结构出现异常：" + e.getMessage());
        }
        return topList;
    }

    /**
     * 封装树
     *
     * @param parentList          要封装为树的父对象集合
     * @param originalList        原始list数据
     * @param PARENT_FIELD_NAME   模型中作为parent字段名称
     * @param CHILDREN_FIELD_NAME 模型中作为children的字段名称
     */
    public static <T> void fillTree(List<T> parentList, List<T> originalList, String PARENT_FIELD_NAME,
        String CHILDREN_FIELD_NAME) throws Exception {
        for (T t : parentList) {
            List<T> children = fillChildren(t, originalList, PARENT_FIELD_NAME, CHILDREN_FIELD_NAME);
            if (children.isEmpty()) {
                continue;
            }
            originalList.removeAll(children);
            fillTree(children, originalList, PARENT_FIELD_NAME, CHILDREN_FIELD_NAME);
        }
    }

    /**
     * 封装子对象
     *
     * @param parent              父对象
     * @param originalList        待处理对象集合
     * @param PARENT_FIELD_NAME   模型中作为parent字段名称
     * @param CHILDREN_FIELD_NAME 模型中作为children的字段名称
     */
    public static <T> List<T> fillChildren(T parent, List<T> originalList, String PARENT_FIELD_NAME,
                                           String CHILDREN_FIELD_NAME) {
        List<T> childList = new ArrayList<>();
        try {
            Long parentId = (Long) BeanUtils.getPropertyDescriptor(parent.getClass(), KEY_NAME)
                    .getReadMethod().invoke(parent);
            for (T t : originalList) {
                Long childParentId = (Long) BeanUtils.getPropertyDescriptor(t.getClass(), PARENT_FIELD_NAME)
                        .getReadMethod().invoke(t);
                if (parentId.equals(childParentId)) {
                    childList.add(t);
                }
            }
            if (!childList.isEmpty()) {
                FieldUtils.writeDeclaredField(parent, CHILDREN_FIELD_NAME, childList, true);
            }
        } catch (Exception e) {
            log.error("封装子对象出现异常：", e);
            throw new BusinessException(500, "封装子对象出现异常：" + e.getMessage());
        }
        return childList;
    }
}
